package stalkerdns;

import shared.Mensagem;
import java.util.logging.Level;
import java.util.logging.Logger;
import shared.ClientEntity;
import java.io.*;
import java.net.*;
import com.sun.org.apache.xerces.internal.dom.AttributeMap;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.util.Properties;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Attr;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DNSWorker extends Thread {

    private Socket sock;
    //private static String ClientsPathXML = "c:\\StalkerDNS.xml"; //CORRIGIR: não existe 'c:\\' na snarf..
    //private static String StatusON = "online";
    private Mensagem MsgToClient;
    private Mensagem MsgfromClient;
    private byte[] ByteBuffer;
    private Hashtable Tabela;
    private ClientEntity cliente = new ClientEntity();

    public DNSWorker(Socket s, Hashtable tabela) { // recebe o socket ativo no construtor
        sock = s;
        Tabela = tabela;
    }

    @Override
    public void run() {
        System.out.println("Worker - nova thread iniciando ...");
        MsgToClient = new Mensagem();
        MsgfromClient = new Mensagem();
        ObjectInputStream in = null;
        ObjectOutputStream out = null;

        try {
            // obtem os fluxos que fazem parte do Socket TCP
            // e "encapsula" os mesmos em fluxos de objeto
            in = new ObjectInputStream(sock.getInputStream());
            out = new ObjectOutputStream(sock.getOutputStream());

            ByteBuffer = new byte[1024];
            in.read(ByteBuffer);

            MsgfromClient.convertToClass(ByteBuffer);


            switch (MsgfromClient.getCdTransacao()) {
                case 1:
                    LogOn();
                    break;
                case 2:
                    LogOff();
                    break;
                //case 3:
                //   SetBusy();
                //   break;
                case 4:
                    StartChat();
                    break;
                case 5:
                    EndChat();
                    break;
            }

            //MsgToClient.setCdTransacao(MsgfromClient.getCdTransacao());
            //MsgToClient.setIp(MsgfromClient.getIp());
            //MsgToClient.setPorta(MsgfromClient.getPorta());
            //MsgToClient.setTexto("OK");


            out.write(MsgToClient.convertToByteBuffer());
            out.flush();

            // fecha o socket e acabou o servi�o
            // se precisar de muitas intera��es, tem que fazer um loop...
            in.close();
            out.close();
            sock.close();

        } catch (Exception e) {
            try {
                MsgToClient.setCdTransacao(MsgfromClient.getCdTransacao());
                MsgToClient.setIp(MsgfromClient.getIp());
                MsgToClient.setPorta(MsgfromClient.getPorta());
                MsgToClient.setTexto("NOK!");

                out.write(MsgToClient.convertToByteBuffer());
                System.out.println(e);
            } catch (IOException ex) {
                Logger.getLogger(DNSWorker.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    private void LogOn() {
        cliente = new ClientEntity();
        cliente.SetClientIp(MsgfromClient.getIp());
        cliente.SetClientPort(MsgfromClient.getPorta());
        cliente.SetClientName(MsgfromClient.getTexto());
        cliente.SetClientStatus("ON");

        Tabela.put(cliente.GetClientName().trim(), cliente);
        MsgToClient.setTexto("OK");
    }

    private void LogOff() {
        Tabela.remove(MsgfromClient.getTexto().trim());
        MsgToClient.setTexto("OK");
    }

    //private void SetBusy() {
    //}
    private void StartChat() {

        String[] clientNicks = MsgfromClient.getTexto().split(" ");
        ClientEntity c = (ClientEntity) Tabela.get(clientNicks[1].trim());

        if (c != null) {
            if (c.GetClientStatus().equals("ON")) {
                c.SetClientStatus("OCUPADO");
                ((ClientEntity) Tabela.get(clientNicks[0].trim())).SetClientStatus("OCUPADO");

                MsgToClient.setTexto("ON");
                MsgToClient.setIp(c.GetClientIp());
                MsgToClient.setPorta(c.GetClientPort());
            } else if (c.GetClientStatus().equals("OCUPADO")) {
                MsgToClient.setTexto("OCUPADO");
            }
            //else if (c.GetClientStatus().equals("OFF"))
            //            MsgToClient.setTexto("OFF");
        } else {
            MsgToClient.setTexto("OFF");
        }
    }

    private void EndChat() {

        String[] clientNicks = MsgfromClient.getTexto().split(" ");
        ClientEntity c1 = (ClientEntity) Tabela.get(clientNicks[0].trim());
        ClientEntity c2 = (ClientEntity) Tabela.get(clientNicks[1].trim());

        c1.SetClientStatus("ON");
        c2.SetClientStatus("ON");

        MsgToClient.setTexto("OK");
    }
}
